using System;
using System.Collections.Generic;
using System.Text;
using AWSSoapLib.com.amazonaws.s3;

using System.Security.Cryptography.X509Certificates;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;


namespace AWSSoapLib
{
    public class AWSLibrary
    {
        public AmazonEC2Wse ec2;
        private ServicePolicy sp;
        public static string CERT_FILE;

        /// <summary>
        /// This is the constructor that takes a path to a cert file. In order for this to work you must
        /// use a tool like OPENSSL to combine the public cert and private key issued by Amazon into a single
        /// pkcs p12 file. 
        /// 
        /// First, issue a new Cert for you Amazon account and save both PEM files (private key and cert)
        /// Second - use OpenSSL to combine them into a P12 file.
        /// 
        /// Example to do this: 
        /// OpenSSL> pkcs12 -export -inkey PRIVKEY.PEM -in CERT.PEM -out AWSCertificate.p12 -nodes
        /// 
        /// Once done, you can pass that P12 file to this constructor and use the SOAP library
        /// </summary>
        /// <param name="publicKey"></param>
        public AWSLibrary(string publicKey)
        {
            if (publicKey == null) { return; }
            CERT_FILE = publicKey;

            ec2 = new AmazonEC2Wse();
            sp = new ServicePolicy();
            ec2.SetPolicy(sp);

        }

        /// <summary>
        /// This class extends Policy so that Web Services/SOAP policy can be programmatically set instead
        /// of through a policy XML file
        /// </summary>
        public class ServicePolicy : Policy
        {

            public ServicePolicy()
                : base()
            {
                // Create a new instance of the MutualCertificate11 turnkey security assertion.
                //MutualCertificate11Assertion assertion = new MutualCertificate11Assertion();
                // Specify a security token provider for the Web service's security credentials.
                //assertion.ServiceX509TokenProvider = new X509TokenProvider(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer");

                //MutualCertificate10Assertion assertion = new MutualCertificate10Assertion();
                AWSMutualCertificate10Assertion assertion = new AWSMutualCertificate10Assertion();

                assertion.EstablishSecurityContext = false;
                assertion.RenewExpiredSecurityContext = true;
                assertion.RequireSignatureConfirmation = false;
                assertion.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
                assertion.RequireDerivedKeys = false;
                assertion.TtlInSeconds = 300;


                //These grab the Cert from the store (has to have been imported)
                //assertion.ServiceX509TokenProvider = new X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "51xh7n5ppwvf", X509FindType.FindBySubjectName);
                //assertion.ClientX509TokenProvider = new X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "51xh7n5ppwvf", X509FindType.FindBySubjectName);

                //This version uses a custom Provider to merely supply the cert we specified
                assertion.ServiceX509TokenProvider = new JDX509TokenProvider();
                assertion.ClientX509TokenProvider = new JDX509TokenProvider();

                //X509TokenProvider x5 = new X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "51xh7n5ppwvf", X509FindType.FindBySubjectName);
                //X509SecurityToken st = x5.GetToken();

                assertion.Protection.Request.SignatureOptions = 0;
                assertion.Protection.Request.SignatureOptions |= SignatureOptions.IncludeAddressing;
                assertion.Protection.Request.SignatureOptions |= SignatureOptions.IncludeTimestamp;
                assertion.Protection.Request.SignatureOptions |= SignatureOptions.IncludeSoapBody;

                assertion.Protection.Request.EncryptBody = false;

                // Add the policy assertion to the policy.
                this.Assertions.Add(assertion);
            }

        }

        /// <summary>
        /// Used to override the default provider which supplies the cert from the MS Cert Store
        /// We, instead, want to specify a p12 file to load the cert and use to SOAP sign
        /// NOTE: The X509Certificate2(CERT_FILE, "") call has the " " because the cert itself has a password that
        /// is blank. Even though there is a an overloaded version that does not take a password, it will not work
        /// </summary>
        public class JDX509TokenProvider : X509TokenProvider
        {
            public string X509Certificate;

            public override X509SecurityToken GetToken()
            {
                return new X509SecurityToken(new X509Certificate2(CERT_FILE, ""));
            }
        }

        /// <summary>
        /// This class is a simple override for the SOAPFilter
        /// </summary>
        class AWSMutualCertificate10Assertion : MutualCertificate10Assertion
        {
            public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
            {
                return null;
            }
        }
    }
}
